package com.swx.identityservice.filter;


import com.swx.identityservice.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
 * springboot安全策略
 *
 * @author lxh
 * @version V1.0.0
 * @date 2018-6-14 10:05
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;
    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private TokenService tokenService;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 定义了哪些URL路径应该被保护，哪些不应该
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().authorizeRequests()//禁用csrf跨站请求伪造
            .antMatchers("/userregister", "/login", "/getdeptsastree","/login1", "editpermission","addpermission","/swagger-ui.html","/getrolesbydeptid","/{yyyy}-{MM}-{dd}/*", "/getpermissionsbyuserid", "/getDeptsAndRolesAsTree","/getpermissions","/getdealroles", "/getpermissionbyuserid","/selectdeptslist","/selectunit","/getrolesbydeptid","/gethandlebusinessservice").permitAll()
            .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/swagger-resources/configuration/ui", "/swagger-ui.html").permitAll()
            .anyRequest().authenticated();
        http.formLogin().loginPage("/login.html").loginProcessingUrl("/login")
            .successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).and()
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
        http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);

        http.headers().cacheControl();//必须加这个，不然过滤器会报错
        //新增token过滤器
        TokenFilter tokenFilter = new TokenFilter();
        tokenFilter.setTokenService(tokenService);
        tokenFilter.setUserDetailsService(userDetailsService);
        tokenFilter.afterPropertiesSet();
        http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 例如, 可以使用以下配置在内存中进行注册公开内存的身份验证
     * 在内存中添加 user 和 admin 用户
     * 添加 UserDetailsService， 实现自定义登录校验
     */
    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
//        authenticationManagerBuilder.inMemoryAuthentication().withUser("user").password("admin").roles("USER");
        authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }
}
